package com.ruoyi.common.service;

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.config.FinancialDataCacheConfig;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.CachePrefix;
import com.ruoyi.common.utils.AllTickApiUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 统一的金融数据服务类
 * 集成Redis缓存，统一管理外汇、黄金、商品数据的获取和处理
 */
@Slf4j
@Service
public class FinancialDataService {
    
    @Autowired
    private RedisCache redisCache;
    
    // UniRateAPI配置
    private static final String UNI_RATE_API_URL = "https://api.unirateapi.com/api/rates";
    private static final String UNI_RATE_API_KEY = "BjVY2cmSGW8PhG0jFr8FWlI8chdGOgh7FfrrJI6mRXGR1N4tqaFJ3wnnylXOXGfD";
    
    // 缓存API原始数据的键
    private static final String API_RAW_DATA_KEY = "financial_api_raw_data";
    
    /**
     * 获取所有金融数据（外汇+贵金属+商品）
     * 优先从缓存获取，缓存失效时调用API刷新
     */
    public Map<String, String> getAllFinancialData() {
        Map<String, String> result = new ConcurrentHashMap<>();
        
        // 1. 尝试从缓存获取API原始数据
        String cachedRawData = getCachedApiRawData();
        
        if (cachedRawData != null) {
            log.info("使用缓存的API原始数据");
            // 从缓存数据中提取所有需要的币种
            result.putAll(processRawDataToAllSymbols(cachedRawData));
        } else {
            log.info("缓存失效，重新获取API数据");
            // 2. 缓存失效，重新获取API数据
            String rawData = fetchApiRawData();
            if (rawData != null) {
                // 缓存原始数据
                cacheApiRawData(rawData);
                // 处理数据
                result.putAll(processRawDataToAllSymbols(rawData));
            } else {
                log.error("API调用失败，使用降级数据");
                // 3. API失败，使用降级策略
                result.putAll(getFallbackData());
            }
        }
        
        return result;
    }
    
    /**
     * 获取外汇数据
     */
    public Map<String, String> getForexData() {
        Map<String, String> allData = getAllFinancialData();
        Map<String, String> forexData = new HashMap<>();
        
        for (String symbol : FinancialDataCacheConfig.FOREX_SYMBOLS) {
            if (allData.containsKey(symbol)) {
                forexData.put(symbol, allData.get(symbol));
            }
        }
        
        return forexData;
    }
    
    /**
     * 获取贵金属数据
     */
    public Map<String, String> getMetalData() {
        Map<String, String> allData = getAllFinancialData();
        Map<String, String> metalData = new HashMap<>();
        
        for (String symbol : FinancialDataCacheConfig.METAL_SYMBOLS) {
            if (allData.containsKey(symbol)) {
                metalData.put(symbol, allData.get(symbol));
            }
        }
        
        return metalData;
    }
    
    /**
     * 获取商品数据（已禁用，返回空数据）
     */
    public Map<String, String> getCommodityData() {
        Map<String, String> commodityData = new HashMap<>();
        
        // 商品数据已禁用，不再请求外部API
        // 如需要商品数据，请在FinancialDataCacheConfig中启用COMMODITY_SYMBOLS
        log.info("商品数据已禁用，返回空数据");
        
        return commodityData;
    }
    
    /**
     * 获取单个品种的数据
     */
    public String getSymbolData(String symbol) {
        Map<String, String> allData = getAllFinancialData();
        return allData.get(symbol.toUpperCase());
    }
    
    /**
     * 批量获取指定品种的数据
     */
    public Map<String, String> getBatchSymbolData(List<String> symbols) {
        Map<String, String> allData = getAllFinancialData();
        Map<String, String> result = new HashMap<>();
        
        for (String symbol : symbols) {
            String upperSymbol = symbol.toUpperCase();
            if (allData.containsKey(upperSymbol)) {
                result.put(upperSymbol, allData.get(upperSymbol));
            }
        }
        
        return result;
    }
    
    /**
     * 从缓存获取API原始数据
     */
    private String getCachedApiRawData() {
        String cacheKey = CachePrefix.FINANCIAL_API_RAW_DATA.getPrefix() + API_RAW_DATA_KEY;
        return redisCache.getCacheObject(cacheKey);
    }
    
    /**
     * 缓存API原始数据
     */
    private void cacheApiRawData(String rawData) {
        String cacheKey = CachePrefix.FINANCIAL_API_RAW_DATA.getPrefix() + API_RAW_DATA_KEY;
        redisCache.setCacheObject(cacheKey, rawData, 
            FinancialDataCacheConfig.API_RAW_DATA_CACHE_SECONDS, TimeUnit.SECONDS);
    }
    
    /**
     * 调用API获取原始数据
     */
    private String fetchApiRawData() {
        try {
            String result = HttpRequest.get(UNI_RATE_API_URL + "?from=USD&api_key=" + UNI_RATE_API_KEY)
                    .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
                    .header("Authorization", "Bearer " + UNI_RATE_API_KEY)
                    .timeout(FinancialDataCacheConfig.API_TIMEOUT_MS)
                    .execute().body();
            
            log.info("API数据获取成功，数据长度: {}", result.length());
            return result;
            
        } catch (Exception e) {
            log.error("API数据获取失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 处理API原始数据，转换为所有需要的品种数据
     */
    private Map<String, String> processRawDataToAllSymbols(String rawData) {
        Map<String, String> result = new ConcurrentHashMap<>();
        
        try {
            JSONObject json = JSONUtil.parseObj(rawData);
            if (json.containsKey("rates")) {
                JSONObject rates = json.getJSONObject("rates");
                
                // 处理外汇数据
                for (String symbol : FinancialDataCacheConfig.FOREX_SYMBOLS) {
                    String fx678Data = convertToFx678Format(rates, symbol, "forex");
                    if (fx678Data != null) {
                        result.put(symbol, fx678Data);
                    }
                }
                
                // 处理贵金属数据
                for (String symbol : FinancialDataCacheConfig.METAL_SYMBOLS) {
                    String fx678Data = convertToFx678Format(rates, symbol, "metal");
                    if (fx678Data != null) {
                        result.put(symbol, fx678Data);
                    }
                }
                
                // 商品数据已禁用，不再请求外部API
                // 如需要商品数据，请在FinancialDataCacheConfig中启用COMMODITY_SYMBOLS
                for (String symbol : FinancialDataCacheConfig.COMMODITY_SYMBOLS) {
                    String mockData = generateMockData(symbol, "commodity");
                    result.put(symbol, mockData);
                }
            }
            
        } catch (Exception e) {
            log.error("处理API原始数据失败: {}", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 转换为fx678兼容格式
     */
    private String convertToFx678Format(JSONObject rates, String symbol, String dataType) {
        try {
            String targetSymbol = convertToUniRateApiSymbol(symbol);
            
            if (rates.containsKey(targetSymbol)) {
                double rate = rates.getDouble(targetSymbol);
                
                // 对于贵金属，需要取倒数
                if ("metal".equals(dataType) && isPreciousMetal(symbol)) {
                    rate = 1.0 / rate;
                }
                // 对于某些外汇对，需要取倒数
                else if ("forex".equals(dataType) && needsInverseForex(symbol)) {
                    rate = 1.0 / rate;
                }
                
                return AllTickApiUtil.createFx678ArrayFormat(symbol, 0, 0, 0, 0, rate);
            }
            
        } catch (Exception e) {
            log.error("转换{}数据格式失败: {}", dataType, e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 生成模拟数据
     */
    private String generateMockData(String symbol, String dataType) {
        double basePrice = getBasePrice(symbol, dataType);
        double randomChange = (Math.random() - 0.5) * 0.02; // ±1%随机变化
        double currentPrice = basePrice * (1 + randomChange);
        
        return AllTickApiUtil.createFx678ArrayFormat(symbol, 0, 0, 0, 0, currentPrice);
    }
    
    /**
     * 获取基础价格
     */
    private double getBasePrice(String symbol, String dataType) {
        switch (dataType) {
            case "forex":
                return getBaseForexPrice(symbol);
            case "metal":
                return getBaseMetalPrice(symbol);
            case "commodity":
                return getBaseCommodityPrice(symbol);
            default:
                return 1.0;
        }
    }
    
    /**
     * 获取基础外汇价格
     */
    private double getBaseForexPrice(String symbol) {
        switch (symbol.toUpperCase()) {
            // 主要外汇对
            case "EURUSD": return 1.0500;
            case "GBPUSD": return 1.2500;
            case "USDJPY": return 150.00;
            case "USDCHF": return 0.9000;
            case "AUDUSD": return 0.6500;
            case "NZDUSD": return 0.6000;
            case "USDCAD": return 1.3500;
            case "USDHKD": return 7.8000;
            case "USDCNY": return 7.2000;
            case "USDCNH": return 7.2500;
            case "USDKRW": return 1320.00;
            case "USDMXN": return 18.00;
            case "USDTRY": return 27.00;
            case "USDZAR": return 18.50;
            case "USDDKK": return 6.8000;
            case "USDNOK": return 10.50;
            case "USDRUB": return 90.00;
            case "USDSEK": return 10.80;
            case "USDSGD": return 1.3500;
            
            // 交叉汇率 - EUR系列
            case "EURGBP": return 0.8500;
            case "EURJPY": return 157.50;
            case "EURCHF": return 0.9450;
            case "EURNZD": return 1.7500;
            case "EURAUD": return 1.6150;
            case "EURCAD": return 1.4175;
            case "EURCNY": return 7.5600;
            case "EURTRY": return 28.35;
            
            // 交叉汇率 - GBP系列
            case "GBPJPY": return 187.50;
            case "GBPCHF": return 1.1250;
            case "GBPCAD": return 1.6875;
            case "GBPAUD": return 1.9230;
            case "GBPNZD": return 2.0833;
            case "GBPCNY": return 9.0000;
            
            // 交叉汇率 - AUD系列
            case "AUDJPY": return 97.50;
            case "AUDCHF": return 0.5850;
            case "AUDCAD": return 0.8775;
            case "AUDNZD": return 1.0833;
            case "AUDCNY": return 4.6800;
            
            // 交叉汇率 - NZD系列
            case "NZDJPY": return 90.00;
            case "NZDCHF": return 0.5400;
            case "NZDCAD": return 0.8100;
            
            // 交叉汇率 - JPY系列
            case "CHFJPY": return 166.67;
            case "CADJPY": return 111.11;
            case "CNYJPY": return 20.83;
            
            // 交叉汇率 - CHF系列
            case "CADCHF": return 0.6667;
            
            // 交叉汇率 - CNY系列
            case "CNYHKD": return 1.0833;
            case "CADCNY": return 5.3333;
            
            default: return 1.0000;
        }
    }
    
    /**
     * 获取基础贵金属价格（仅黄金）
     */
    private double getBaseMetalPrice(String symbol) {
        switch (symbol.toUpperCase()) {
            case "GOLD":
            case "XAU":
            case "XAUUSD": return 2000.00;
            default: return 100.00;
        }
    }
    
    /**
     * 获取基础商品价格
     */
    private double getBaseCommodityPrice(String symbol) {
        switch (symbol.toUpperCase()) {
            case "OIL":
            case "CRUDE": return 80.00;
            case "GAS": return 3.00;
            case "BRENT": return 82.00;
            default: return 50.00;
        }
    }
    
    /**
     * 获取降级数据
     */
    private Map<String, String> getFallbackData() {
        Map<String, String> result = new HashMap<>();
        
        // 生成所有支持品种的模拟数据
        for (String symbol : FinancialDataCacheConfig.FOREX_SYMBOLS) {
            result.put(symbol, generateMockData(symbol, "forex"));
        }
        
        for (String symbol : FinancialDataCacheConfig.METAL_SYMBOLS) {
            result.put(symbol, generateMockData(symbol, "metal"));
        }
        
        for (String symbol : FinancialDataCacheConfig.COMMODITY_SYMBOLS) {
            result.put(symbol, generateMockData(symbol, "commodity"));
        }
        
        return result;
    }
    
    /**
     * 转换为UniRateAPI符号格式
     */
    private String convertToUniRateApiSymbol(String symbol) {
        switch (symbol.toUpperCase()) {
            // 贵金属（仅黄金）
            case "GOLD":
            case "XAU":
            case "XAUUSD": return "XAU";
            
            // 主要外汇对 - 基础货币
            case "EURUSD": return "EUR";
            case "GBPUSD": return "GBP";
            case "AUDUSD": return "AUD";
            case "NZDUSD": return "NZD";
            
            // 主要外汇对 - 报价货币
            case "USDJPY": return "JPY";
            case "USDCHF": return "CHF";
            case "USDCAD": return "CAD";
            case "USDHKD": return "HKD";
            case "USDCNY": return "CNY";
            case "USDCNH": return "CNH";
            case "USDKRW": return "KRW";
            case "USDMXN": return "MXN";
            case "USDTRY": return "TRY";
            case "USDZAR": return "ZAR";
            case "USDDKK": return "DKK";
            case "USDNOK": return "NOK";
            case "USDRUB": return "RUB";
            case "USDSEK": return "SEK";
            case "USDSGD": return "SGD";
            
            // 交叉汇率 - EUR系列
            case "EURGBP": return "EUR";
            case "EURJPY": return "EUR";
            case "EURCHF": return "EUR";
            case "EURNZD": return "EUR";
            case "EURAUD": return "EUR";
            case "EURCAD": return "EUR";
            case "EURCNY": return "EUR";
            case "EURTRY": return "EUR";
            
            // 交叉汇率 - GBP系列
            case "GBPJPY": return "GBP";
            case "GBPCHF": return "GBP";
            case "GBPCAD": return "GBP";
            case "GBPAUD": return "GBP";
            case "GBPNZD": return "GBP";
            case "GBPCNY": return "GBP";
            
            // 交叉汇率 - AUD系列
            case "AUDJPY": return "AUD";
            case "AUDCHF": return "AUD";
            case "AUDCAD": return "AUD";
            case "AUDNZD": return "AUD";
            case "AUDCNY": return "AUD";
            
            // 交叉汇率 - NZD系列
            case "NZDJPY": return "NZD";
            case "NZDCHF": return "NZD";
            case "NZDCAD": return "NZD";
            
            // 交叉汇率 - JPY系列
            case "CHFJPY": return "CHF";
            case "CADJPY": return "CAD";
            case "CNYJPY": return "CNY";
            
            // 交叉汇率 - CHF系列
            case "CADCHF": return "CAD";
            
            // 交叉汇率 - CNY系列
            case "CNYHKD": return "CNY";
            case "CADCNY": return "CAD";
            
            default: return symbol;
        }
    }
    
    /**
     * 判断是否为贵金属
     */
    private boolean isPreciousMetal(String symbol) {
        return FinancialDataCacheConfig.isMetalSymbol(symbol);
    }
    
    /**
     * 判断外汇对是否需要取倒数
     */
    private boolean needsInverseForex(String symbol) {
        switch (symbol.toUpperCase()) {
            // 主要外汇对 - 基础货币/USD格式
            case "EURUSD":
            case "GBPUSD":
            case "AUDUSD":
            case "NZDUSD":
            
            // 交叉汇率 - EUR系列
            case "EURGBP":
            case "EURJPY":
            case "EURCHF":
            case "EURNZD":
            case "EURAUD":
            case "EURCAD":
            case "EURCNY":
            case "EURTRY":
            
            // 交叉汇率 - GBP系列
            case "GBPJPY":
            case "GBPCHF":
            case "GBPCAD":
            case "GBPAUD":
            case "GBPNZD":
            case "GBPCNY":
            
            // 交叉汇率 - AUD系列
            case "AUDJPY":
            case "AUDCHF":
            case "AUDCAD":
            case "AUDNZD":
            case "AUDCNY":
            
            // 交叉汇率 - NZD系列
            case "NZDJPY":
            case "NZDCHF":
            case "NZDCAD":
            
            // 交叉汇率 - JPY系列
            case "CHFJPY":
            case "CADJPY":
            case "CNYJPY":
            
            // 交叉汇率 - CHF系列
            case "CADCHF":
            
            // 交叉汇率 - CNY系列
            case "CNYHKD":
            case "CADCNY":
                return true;
            default:
                return false;
        }
    }
    
    /**
     * 手动刷新缓存
     */
    public void refreshCache() {
        log.info("手动刷新金融数据缓存");
        String cacheKey = CachePrefix.FINANCIAL_API_RAW_DATA.getPrefix() + API_RAW_DATA_KEY;
        redisCache.deleteObject(cacheKey);
        
        // 重新获取数据
        getAllFinancialData();
    }
    
    /**
     * 清除所有缓存
     */
    public void clearAllCache() {
        log.info("清除所有金融数据缓存");
        String cacheKey = CachePrefix.FINANCIAL_API_RAW_DATA.getPrefix() + API_RAW_DATA_KEY;
        redisCache.deleteObject(cacheKey);
    }
    
    /**
     * 获取缓存状态
     */
    public Map<String, Object> getCacheStatus() {
        Map<String, Object> status = new HashMap<>();
        String cacheKey = CachePrefix.FINANCIAL_API_RAW_DATA.getPrefix() + API_RAW_DATA_KEY;
        
        boolean hasCache = redisCache.hasKey(cacheKey);
        long expireTime = hasCache ? redisCache.getExpire(cacheKey) : 0;
        
        status.put("hasCache", hasCache);
        status.put("expireTime", expireTime);
        status.put("cacheKey", cacheKey);
        
        return status;
    }
} 